package com.shiro.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author ZhangJunqi
 * @Date 2022/3/7 -22:41
 */
@Configuration
public class MyShiroConfig {
    //1 ShiroFilterFactoryBean
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean ();
        //设置安全管理器
        bean.setSecurityManager (defaultWebSecurityManager);
        /*
        * anon：无需认证就能访问
        * authc：认证
        * user：有‘记住我’功能可以使用
        * perms：拥有对某个资源的权限才能访问
        * role：拥有某个角色权限才能访问
        * */
        Map<String,String> filterMap=new LinkedHashMap<> ();
//        filterMap.put ("/user/add","authc");
//        filterMap.put ("/user/update","authc");
        //授权：有先后顺序
        filterMap.put ("/user/add","perms[user:add]");
        filterMap.put ("/user/update","perms[user:update]");
        filterMap.put ("/user/*","authc");

        bean.setFilterChainDefinitionMap (filterMap);
        bean.setLoginUrl ("/toLogin");
        //设置未经授权页面
        bean.setUnauthorizedUrl ("/unauthorized");
        return  bean;
    }

    //2 DefaultWebSecuritymanager
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager ();
        defaultWebSecurityManager.setRealm (userRealm);
        return defaultWebSecurityManager;
    }
    //3 创建realm对象
    @Bean
    public UserRealm userRealm(){
        UserRealm userRealm=new UserRealm ();
        userRealm.setCredentialsMatcher (retryLimitHashedCredentialsMatcher());
        return userRealm;
    }

    //4 添加加密或认证次数限制
    @Bean
    public RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher(){
        //ehCacheManager()
        RetryLimitHashedCredentialsMatcher retryLimitHashedCredentialsMatcher = new RetryLimitHashedCredentialsMatcher(getCacheManager());
        //设置输入最大次数，超过则锁定用户
        retryLimitHashedCredentialsMatcher.setRetryLimitNum (2);
        //如果密码加密,可以打开下面配置
        //加密算法的名称
        //retryLimitHashedCredentialsMatcher.setHashAlgorithmName("MD5");
        //配置加密的次数
        //retryLimitHashedCredentialsMatcher.setHashIterations(1024);
        //是否存储为16进制
        //retryLimitHashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);

        return retryLimitHashedCredentialsMatcher;
    }

    //读取缓存配置
    @Bean
    public CacheManager getCacheManager() {
        // 1.实例化 Shiro 自身的 CacheManager，EhCache 的实现类
        EhCacheManager shiroCacheManager = new EhCacheManager();
        // 2.获取 EhCache 的配置类文件并转成输入流
        InputStream is = null;
        try {
            is = ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache-shiro.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 3.实例化 EhCacheManager 自身对象
        net.sf.ehcache.CacheManager ehCacheManager =new  net.sf.ehcache.CacheManager(is);
        // 4.将 EhCacheManager 自身对象赋值给 Shiro 的 CacheManager
        shiroCacheManager.setCacheManager(ehCacheManager);
        // 5.返回
        return shiroCacheManager;
    }

    //整个shiro——thymeleaf
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
}
